home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / spawno30.zip / SPAWNPTH.ASM < prev    next >
Assembly Source File  |  1990-09-05  |  7KB  |  306 lines

  1.     NAME    spawnpth
  2.     TITLE    Path search for disk-swapping spawn() by Ralf Brown
  3.         PAGE    60,132
  4. ;-----------------------------------
  5. ; (c) Copyright 1990 Ralf Brown  All Rights Reserved
  6. ; This code may be redistributed provided that:
  7. ;    1) this copyright notice remains intact and any changes are clearly
  8. ;       marked
  9. ;       2) no fee of any kind is charged
  10. ;-----------------------------------
  11. ;  assembler defines:
  12. ;   __TINY__, __SMALL__, __COMPACT__, __MEDIUM__, __LARGE__
  13. ;    exactly one of the above must be defined to specify the memory
  14. ;    model in use
  15. ;-----------------------------------
  16.  
  17. IFDEF __HUGE__
  18.   %error Huge model not supported
  19. ENDIF ;__HUGE__
  20.  
  21. __BSS__ equ 1                ; yes, we are using uninitialized storage
  22.         INCLUDE RULES.ASI
  23.  
  24.     Header@             ; set up segment and group definitions
  25.  
  26. FFBLK struc
  27.  ?ffb_reserved db 21 dup (?)
  28.  ?ffb_attr     db ?
  29.  ?ffb_time     dw ?
  30.  ?ffb_date     dw ?
  31.  ?ffb_size     dd ?
  32.  ?ffb_name     db 13 dup (?)
  33. FFBLK ends
  34.  
  35. ; bit flags for the extensions which were found
  36. COM_EXT equ 1
  37. EXE_EXT equ 2
  38. USER_EXT equ 4
  39.  
  40. DSeg@
  41. ExtSym@ _psp,WORD,__CDECL__
  42. ExtSym@ _doserrno,WORD,__CDECL__
  43. DSegEnd@
  44.  
  45. BSeg@
  46. env        dd ?
  47.  
  48. found_ext    db ?     ; which extensions have we found?
  49.  
  50. executable_path db    80 dup (?)   ; size of longest legal path+file+NUL
  51. executable_pad    db    4 dup (?)    ; in case we run over while adding extension
  52.  
  53. ffb        ffblk <>
  54.  
  55. name_incl_path    db ?
  56. BSegEnd@
  57.  
  58.  
  59. CSeg@
  60.     assume    ds:DGROUP
  61.  
  62. ;----------------------------------------------------------------
  63. ; static int pascal check_dir(void) ;
  64. ;     check a single directory for both .COM and .EXE
  65. ;----------------------------------------------------------------
  66. Proc@ CHECK_DIR,__PASCAL__
  67.     push    es
  68.     push    di
  69.     push    ds
  70.     pop    es
  71.     assume    es:DGROUP
  72.     mov    found_ext,0       ; haven't found anything yet
  73.     mov    di,offset DGROUP:executable_path
  74.     mov    cx,size executable_path
  75.     mov    al,0
  76.     cld
  77.     repne    scasb
  78.     dec    di
  79. ; now that we have the end of the name, scan backward to check extension
  80.     mov    bx,di
  81.     mov    dl,0
  82. ext_scan_loop:
  83.     dec    di
  84.     cmp    di,offset DGROUP:executable_path
  85.     je    had_no_ext
  86.         mov     al,[di]
  87.     cmp    al,'.'
  88.     jne    not_dot
  89.     or    dl,dl           ; have we seen a wildcard?
  90.     jne    got_dot
  91.     or    found_ext,USER_EXT ; yes, user specified a particular extension
  92.         jmp short got_extension
  93. not_dot:
  94.         cmp     al,'/'
  95.     je    had_no_ext
  96.     cmp    al,'\'
  97.     je    had_no_ext
  98.     cmp    al,':'
  99.     je    had_no_ext
  100.     cmp    al,'*'
  101.     je    got_wildcard
  102.     cmp    al,'?'
  103.     jne    ext_scan_loop
  104. got_wildcard:
  105.     mov    dl,1
  106.     jmp    ext_scan_loop
  107. had_no_ext:
  108.     mov    di,bx           ; back to end of name
  109.     mov    byte ptr [di],'.'  ; append a period
  110. got_dot:
  111.     inc    di
  112.         mov     word ptr [di],'*'  ; append an asterisk wildcard and NUL
  113. got_extension:
  114.     mov    ah,2Fh           ; get DTA
  115.     MSDOS@
  116.     assume    es:NOTHING
  117.     push    es           ; and store address for later
  118.     push    bx
  119.         mov     dx,offset DGROUP:ffb
  120.         mov     ah,1Ah             ; set DTA to findfirst block
  121.         MSDOS@
  122.         mov     ah,4Eh
  123.         mov     cx,23h             ; search for archive,hidden,and read-only
  124. check_dir_loop:
  125.     mov    dx,offset DGROUP:executable_path
  126.     MSDOS@
  127.     jc    check_no_more
  128.     test    found_ext,USER_EXT
  129.     jnz    check_OK
  130.         mov     bx,offset DGROUP:ffb.?ffb_name
  131. check_found_ext_loop:
  132.     mov    al,[bx]
  133.     inc    bx
  134.     cmp    al,0
  135.     je    checked_ext
  136.     cmp    al,'.'
  137.     jne    check_found_ext_loop
  138.     cmp    word ptr [bx],'OC'
  139.     jne    not_com_ext
  140.     cmp    byte ptr [bx+2],'M'
  141.     jne    not_com_ext
  142.     or    found_ext,COM_EXT
  143.     jmp short check_successful
  144. not_com_ext:
  145.     cmp    word ptr [bx],'XE'
  146.     jne    checked_ext
  147.     cmp    byte ptr [bx+2],'E'
  148.     jne    checked_ext
  149.     or    found_ext,EXE_EXT
  150. checked_ext:
  151.     mov    ah,4Fh
  152.     jmp    check_dir_loop
  153. check_no_more:
  154.     test    found_ext,COM_EXT or EXE_EXT
  155.     je    check_failed       ; neither .COM nor .EXE found
  156. check_successful:
  157.     mov    word ptr [di],'OC'
  158.     mov    ax,'M'
  159.     test    found_ext,COM_EXT
  160.     jne    check_succeeded
  161.     mov    word ptr [di],'XE'
  162.     mov    ax,'E'
  163. check_succeeded:
  164.         mov     word ptr [di+2],ax
  165. check_OK:
  166.     mov    bx,dx
  167.     jmp short check_dir_done
  168. check_failed:
  169.     xor    bx,bx
  170. check_dir_done:
  171.     pop    dx           ; get back original DTA
  172.     pop    ax
  173.     push    ds
  174.     mov    ds,ax
  175.     mov    ah,1Ah
  176.     MSDOS@               ; restore DTA
  177.     pop    ds
  178.     pop    di
  179.     pop    es
  180.     or    bx,bx           ; set ZF if failed
  181.         ret
  182. EndProc@ CHECK_DIR,__PASCAL__
  183.  
  184. ;----------------------------------------------------------------
  185. ; char * pascal __spawn_search(const char *name) ;
  186. ;    given a program name, search the PATH for it, returning the full pathname
  187. ;    or NULL if not found
  188. ;----------------------------------------------------------------
  189. PubProc@ __SPAWN_SEARCH,__PASCAL__
  190. ; parameters
  191. if ldata
  192.  @name = dword ptr [bp+2+cPtrSize]
  193. else
  194.  @name = word ptr [bp+2+cPtrSize]
  195. endif
  196. ; start of subroutine
  197.     push    bp
  198.     mov    bp,sp
  199.     push    es
  200.     push    di
  201.     push    si
  202. ; set up pointer to environment
  203.     mov    es,_psp@
  204.     mov    es,es:[002Ch]
  205.     xor    di,di
  206.     jmp short find_path
  207. find_path_loop:
  208.     cmp    byte ptr es:[di],0
  209.     je    found_path
  210. find_path_loop2:
  211.         inc     di
  212.     cmp    byte ptr es:[di-1],0
  213.     jne    find_path_loop2
  214. find_path:
  215.     cmp    word ptr es:[di],'AP'
  216.     jne    find_path_loop
  217.     cmp    word ptr es:[di+2],'HT'
  218.     jne    find_path_loop
  219.     cmp    byte ptr es:[di+4],'='
  220.     jne    find_path_loop
  221.     add    di,5
  222. found_path:
  223.     mov    word ptr env+2,es
  224.     mov    word ptr env,di
  225.     mov    di,offset DGROUP:executable_path
  226.         cld
  227. search_loop:
  228.     mov    name_incl_path,0
  229.         push    ds
  230.         pop     es
  231.         assume  es:DGROUP
  232.     ; append @name to executable_path
  233.         pushDS_
  234.     LDS_    si,@name
  235. copy_cur_loop:
  236.     cmp    di,offset DGROUP:executable_pad
  237.     jae    copy_cur_done
  238.         lodsb
  239.     stosb
  240.     cmp    al,'/'
  241.     je    name_has_path
  242.     cmp    al,'\'
  243.     jne    name_no_path
  244. name_has_path:
  245.     mov    name_incl_path,1
  246. name_no_path:
  247.     or    al,al
  248.     jnz    copy_cur_loop
  249. copy_cur_done:
  250.         popDS_
  251.     call    check_dir@
  252.     jnz    search_successful
  253.     cmp    name_incl_path,0
  254.     jne    search_failed       ; don't look at PATH unless simple filename
  255.     les    bx,env
  256.     cmp    byte ptr es:[bx],0
  257.     je    search_failed
  258.     mov    di,offset DGROUP:executable_path
  259. dir_copy_loop:
  260.         mov     al,es:[bx]
  261.     or    al,al
  262.     je    dir_copy_done
  263.     inc    bx
  264.     cmp    al,';'             ; separator for path entries
  265.     je    dir_copy_done
  266.     mov    [di],al
  267.     inc    di
  268.         cmp     di,offset DGROUP:executable_pad   ; make sure we don't overrun buf
  269.     jb    dir_copy_loop
  270. dir_copy_done:
  271.     mov    al,[di-1]
  272.         cmp     al,'/'             ; was last char a slash or backslash?
  273.     je    dir_has_slash
  274.     cmp    al,'\'
  275.     je    dir_has_slash
  276.     cmp    al,':'             ; no slash if only drive letter
  277.     je    dir_has_slash
  278.     mov    byte ptr [di],'/'
  279.     inc    di
  280. dir_has_slash:
  281.     mov    word ptr env,bx
  282.     jmp    search_loop
  283.  
  284. search_successful:
  285.     mov    ax,bx
  286. if ldata
  287.     mov    dx,ds
  288. endif
  289.     jmp short search_done
  290. search_failed:
  291.     mov    _doserrno@,2      ; file not found
  292.         xor     ax,ax
  293. if ldata
  294.     xor    dx,dx
  295. endif
  296. search_done:
  297.     pop    si
  298.     pop    di
  299.     pop    es
  300.         pop     bp
  301.     ret    dPtrSize
  302. EndProc@ __SPAWN_SEARCH,__PASCAL__
  303.  
  304. CSegEnd@
  305.     END
  306.